package com.yic.module.mes.service.report;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.yic.framework.common.util.collection.CollectionUtils;
import com.yic.module.mes.dal.dataobject.mo.MoDO;
import com.yic.module.mes.dal.dataobject.modetail.MoDetailDO;
import com.yic.module.mes.dal.dataobject.moroute.MoRouteDO;
import com.yic.module.mes.dal.dataobject.report.ReportDO;
import com.yic.module.mes.service.modetail.MoDetailService;
import com.yic.module.mes.service.moroute.MoRouteService;
import com.yic.module.system.enums.dict.MesProcessLinkEnum;
import com.yic.module.system.enums.dict.MesSerialTypeEnum;
import com.yic.module.system.enums.dict.SystemBooleanEnum;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import static com.yic.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.yic.module.mes.enums.ErrorCodeConstants.*;

/**
 * @Author: Ljx
 * @createTime: 2023年11月30日 09:51:03
 * @version: v1.0.0
 * @Description: 序列号报工实现
 */
@Service("serial")
public class SerialReportTempleteImpl extends ReportTemplete {

    @Resource
    private ReportService reportService;
    @Resource
    private MoRouteService moRouteService;
    @Resource
    private MoDetailService moDetailService;

    @Override
    protected void checkReportType(MoDO moDO) {
        if (moDO.getSnType().equals(MesSerialTypeEnum.NO.getMesSerialType())) {
            throw exception(REPORT_TYPE_NOT_MATE);
        }
    }

    @Override
    protected void checkSerialNo(Long moId, Long moRouteId, String serialNo) {
        //校验流水号是否在允许范围内
        MoDetailDO moDetail = moDetailService.getMoDetail(moId, serialNo);
        if (ObjectUtil.isEmpty(moDetail)) {
            throw exception(REPORT_SERIAL_NOT_EXISTS);
        }
        //校验当前流水号是否已被使用
        ReportDO curReportDO = reportService.getReportBySerialNo(moId, moRouteId, serialNo);
        if (ObjectUtil.isNotEmpty(curReportDO)) {
            throw exception(REPORT_SERIAL_USED);
        }
    }

    @Override
    protected void checkProcess(Long moId, Long moRouteId, BigDecimal reportAmount, BigDecimal produceAmount, String serialNo) {
        // 不能为空，并且报工数量只能为1
        if (StrUtil.isBlank(serialNo)) {
            throw exception(REPORT_SERIAL_NOT_EMPTY);
        }
        if (reportAmount.compareTo(new BigDecimal("1")) != 0) {
            throw exception(REPORT_SERIAL_REPORT_AMOUNT_ONE);
        }
        // 获取工单工艺路线
        List<MoRouteDO> moRoutes = moRouteService.getMoRouteByMoId(moId);
        if (CollectionUtil.isEmpty(moRoutes)) {
            throw exception(MO_ROUTE_NOT_EXISTS);
        }
        MoRouteDO curRoute = null;
        MoRouteDO upRoute = null;
        MoRouteDO mainRoute = null;
        for (int i = 0; i < moRoutes.size(); i++) {
            MoRouteDO moRoute = moRoutes.get(i);
            // 获取当前工序
            if (moRoute.getId().equals(moRouteId)) {
                curRoute = moRoute;
                if (moRoute.getSubsequence() > 1) { // 获取上一道工序
                    List<MoRouteDO> moRouteDOS = moRoutes.stream().filter(moRouteDO -> moRouteDO.getSubsequence().equals(moRoute.getSubsequence() - 1)).collect(Collectors.toList());
                    if (CollectionUtil.isEmpty(moRouteDOS)) {
                        throw exception(MO_ROUTE_ERROR);
                    }
                    upRoute = CollectionUtils.getFirst(moRouteDOS);
                }
            }
            if (moRoute.getMainProcess().equals(SystemBooleanEnum.YES.getSystemBoolean())) {
                mainRoute = moRoute;
            }
        }
        //校验当前工序报工数量不允许超过排产数量
        List<ReportDO> list = reportService.getReportByMoRouteId(moRouteId);
        if (CollectionUtil.isNotEmpty(list)) {
            BigDecimal amount = list.stream().map(ReportDO::getReportAmount).reduce(BigDecimal.ZERO, BigDecimal::add); //已报功数量
            if (produceAmount.subtract(amount).compareTo(reportAmount) < 0) {
                throw exception(REPORT_AMOUNT_EXCEED);
            }
        }

        //校验关键工序
        if (ObjectUtil.isNotEmpty(mainRoute)) {
            //查询关键工序是否已经报工，如果关键工序已报功，则关键工序之前的工序均无法报工
            ReportDO mainReport = reportService.getReportBySerialNo(moId, mainRoute.getId(), serialNo);
            if (ObjectUtil.isNotEmpty(mainReport) && mainRoute.getSubsequence()> curRoute.getSubsequence()) {
                throw exception(REPORT_MAIN_ROUTE_CREATED);
            }
        }
        //校验上道工序
        if (ObjectUtil.isNotEmpty(upRoute) && upRoute.getLink().equals(MesProcessLinkEnum.ES.getMesProcessLink())) {
            // 查询上道工序是否已经报工
            ReportDO upReportDO = reportService.getReportBySerialNo(moId, upRoute.getId(), serialNo);
            if (ObjectUtil.isEmpty(upReportDO)) {
                throw exception(REPORT_NOT_UP_PROCESS);
            }
        }

    }

    @Override
    protected void reduceInventory() {
        //TODO 入库

    }

    @Override
    protected void increaseInventory() {
        //TODO 出库

    }

    @Override
    protected void saveProduce() {
        //保存生产数据

    }
}
